from qiniu import Auth, put_file, etag, urlsafe_base64_encode
import qiniu.config

from PySide6.QtCore import QThread, Signal
import json
import requests
import urllib.request
import time


class QiniuPartThread(QThread):
    trigger = Signal(dict)

    def __init__(self, token, uid, idx, data):
        super().__init__()
        self.token = token
        self.uid = uid
        self.idx = idx
        self.data = data

    def run(self):
        url = f"http://up-cn-east-2.qiniup.com/buckets/3vppt/objects/~/uploads/{self.uid}/{self.idx}"
        headers = {
            "Host": "up-cn-east-2.qiniup.com",
            "Content-Type": "application/octet-stream",
            "Authorization": f"UpToken {self.token}",
            "Content-Length": str(len(self.data)),
        }
        while True:
            try:
                print("分片上传", self.idx)
                res = requests.put(url, headers=headers, data=self.data, verify=False)
                r = res.json()
            except BaseException as err:
                print("分片错误", self.idx, err)
            else:
                print("分片完成", self.idx, r)
                self.trigger.emit({"etag": r.get("etag"), "partNumber": self.idx})
                break
            time.sleep(2)


class QiniuThread(QThread):
    trigger = Signal(dict)
    speed = Signal(int)
    is_running = True

    def __init__(self):
        super().__init__()

    def stop(self):
        self.is_running = False

    def setFile(self, file):
        self.file = file

    def setToken(self, token):
        self.token = token

    def hasUploadId(self):
        """请求任务ID"""
        url = "http://up-cn-east-2.qiniup.com/buckets/3vppt/objects/~/uploads"
        headers = {
            "Host": "up-cn-east-2.qiniup.com",
            "Authorization": f"UpToken {self.token}",
        }
        try:
            res = requests.post(url, headers=headers, verify=False)
            r = res.json()
        except BaseException as err:
            print(err)
        else:
            return r

    def finishedPart(self, e):
        """分片上传完成回调"""
        print("分片回调", e)
        self.parts.append(e)
        v = int(len(self.parts) / len(self.threads) * 100)
        self.speed.emit(v)

    def finishedUpload(self, uid):
        url = f"http://up-cn-east-2.qiniup.com/buckets/3vppt/objects/~/uploads/{uid}"
        headers = {
            "Host": "up-cn-east-2.qiniup.com",
            "Content-Type": "application/json",
            "Authorization": f"UpToken {self.token}",
        }
        sorted_x = sorted(self.parts, key=lambda x: x["partNumber"])
        data = {"parts": sorted_x, "fname": self.file.split("/")[-1]}
        try:
            res = requests.post(
                url, headers=headers, data=json.dumps(data), verify=False
            )
            r = res.json()
        except BaseException as err:
            print(err)
        else:
            return r

    def run(self):
        # SDK上传
        # key = "bbbb.avi"
        # ret = put_file(self.token, key, self.file)
        # print("qiniu: ", ret)
        # self.trigger.emit({"res": ret})

        # API上传
        # url = "http://up-cn-east-2.qiniup.com"
        # headers = {
        #     "Host": "up-cn-east-2.qiniup.com",
        #     "Content-Type": "multipart/form-data;",
        # }
        # data = {
        #     "upload_token": self.token,
        #     "fileName": self.file,
        #     "fileBinaryData": open(self.file, "rb").read(),
        # }
        # try:
        #     res = requests.post(url, headers=headers, data=data, verify=False)
        #     r = res.json()
        # except BaseException as err:
        #     print(err)
        # else:
        #     print("qiniu: ", r)
        #     self.trigger.emit(r)

        # API分片v2
        self.threads = []
        self.parts = []
        m = self.hasUploadId()
        print("qiniu: ", m)
        idx = 1
        chunk_size = 1024 * 1024
        with open(self.file, "rb") as input_file:
            while True:
                data = input_file.read(chunk_size)  # 读取数据块
                if not data:
                    break  # 如果没有数据了，结束循环
                print(idx, len(data), "\n")  # 写入数据块到输出文件
                # self.postUploadId(m["uploadId"], idx, data)
                self.threads.append(
                    QiniuPartThread(self.token, m["uploadId"], idx, data)
                )
                idx += 1
        for t in self.threads:
            t.trigger.connect(self.finishedPart)
            t.start()
        for t in self.threads:
            t.wait()
        u = self.finishedUpload(m["uploadId"])
        print("合并文件:", u)
        self.trigger.emit(u)
